Source code for hysop.backend.device.codegen.structs.indices

# Copyright (c) HySoP 2011-2024
#
# This file is part of HySoP software.
# See "https://particle_methods.gricad-pages.univ-grenoble-alpes.fr/hysop-doc/"
# for further info.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


import numpy as np

from hysop.tools.htypes import check_instance, first_not_None
from hysop.tools.misc import upper_pow2_or_3
from hysop.backend.device.codegen.base.enum_codegen import EnumCodeGenerator
from hysop.backend.device.codegen.base.struct_codegen import StructCodeGenerator
from hysop.backend.device.opencl.opencl_types import OpenClTypeGen
from hysop.constants import DirectionLabels


[docs] class SpaceIndices(StructCodeGenerator): def __init__( self, name, typegen, var_prefix, stype, workdim, vsize=1, typedef=True, comments=None, ): assert vsize in [1, 2, 3, 4, 8, 16] stype = stype.replace("fbtype", typegen.fbtype) name += f"{workdim}D_{stype.capitalize()}{vsize}" if isinstance(typedef, bool): if typedef is True: typedef = name + "_s" else: typedef = None dtype = self.build_dtype(typegen, var_prefix, stype, vsize, workdim) super().__init__( name=name, dtype=dtype, typegen=typegen, typedef=typedef, comments=comments ) self.workdim = workdim self.vsize = vsize self.stype = stype
[docs] @staticmethod def build_dtype(typegen, var_prefix, stype, vsize, workdim): tg = typegen stype1 = tg.dtype_from_str(stype) stypen = tg.dtype_from_str(f"{stype}{vsize}") dtype = [] fn = f"{var_prefix}{DirectionLabels[0]}" field = (fn, stypen) dtype.append(field) for i in range(workdim - 2, -1, -1): fn = f"{var_prefix}{DirectionLabels[workdim-1-i]}" field = (fn, stype1) dtype.append(field) return np.dtype(dtype)
[docs] def create(self, *args, **kwds): raise NotImplementedError()
[docs] class GlobalIndices(SpaceIndices): def __init__(self, typegen, workdim, **kwds): super().__init__( typegen=typegen, workdim=workdim, name="GlobalIndices", var_prefix="I", stype="int", **kwds, )
[docs] class GlobalCoordinates(SpaceIndices): def __init__(self, typegen, workdim, **kwds): super().__init__( typegen=typegen, workdim=workdim, name="GlobalCoordinates", var_prefix="", stype="fbtype", **kwds, )
[docs] class GlobalFieldInfo(StructCodeGenerator): def __init__(self, typegen, workdim, vsize, typedef=True, **kwds): gi = GlobalIndices(typegen=typegen, workdim=workdim, vsize=vsize) gc = GlobalCoordinates(typegen=typegen, workdim=workdim, vsize=vsize) dtype = self.build_dtype(gi, gc) name = "GlobalFieldInfo{}D_{}{}_{}{}".format( workdim, gi.stype.capitalize(), vsize, gc.stype.capitalize(), vsize ) if isinstance(typedef, bool): if typedef is True: typedef = name + "_s" else: typedef = None super().__init__( name=name, dtype=dtype, typedef=typedef, typegen=typegen, **kwds ) self.require(gi.name, gi) self.require(gc.name, gc) self.workdim = workdim self.vsize = vsize
[docs] @staticmethod def build_dtype(gi, gc): dtype = [("idx", gi.dtype), ("pos", gc.dtype)] return np.dtype(dtype)
[docs] class GlobalFieldInfos(StructCodeGenerator): def __init__(self, field_names, typegen, workdim, vsize, typedef=True, **kwds): gfi = GlobalFieldInfo(typegen=typegen, workdim=workdim, vsize=vsize) dtype = [] for fname in field_names: field = (fname, gfi.dtype) dtype.append(field) dtype = np.dtype(dtype) name = gfi.name.replace("GlobalFieldInfo", "GlobalFieldInfos") name += "_" + "_".join(field_names) if isinstance(typedef, bool): if typedef is True: typedef = name + "_s" else: typedef = None super().__init__( name=name, dtype=dtype, typedef=typedef, typegen=typegen, **kwds ) self.require(gfi.name, gfi) self.field_names = field_names self.workdim = workdim self.vsize = vsize
if __name__ == "__main__": from hysop.backend.device.codegen.base.opencl_codegen import OpenClCodeGenerator from hysop.backend.device.codegen.base.test import _test_typegen tg = _test_typegen("double", float_dump_mode="dec") idx = GlobalIndices(typegen=tg, workdim=3, vsize=4) pos = GlobalCoordinates(typegen=tg, workdim=3, vsize=4) gfi = GlobalFieldInfo(typegen=tg, workdim=3, vsize=2) gfis = GlobalFieldInfos(typegen=tg, workdim=2, vsize=8, field_names=("P", "V")) cg = OpenClCodeGenerator("test_generator", tg) cg.require("idx", idx) cg.require("pos", pos) cg.require("gfi", gfi) cg.require("gfis", gfis) cg.edit() cg.test_compile()